'''
交互式调整标注
手动调整 labelmepose标注


下一张： 空格
上一张： B
放大：ctrl + 滚轮
平移：ctrl + 左键拖动
'''
import glob
import math
import random
import sys
import traceback
from functools import partial

import cv2
import numpy
import numpy as np
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QComboBox
from PyQt5.QtCore import Qt, QRectF, QPointF, QLineF
from PyQt5.QtGui import QPainter, QPixmap, QImage, QPen, QColor, QFont, QCursor

import yaml
import json

# from log import saved_algo_param_dict #
saved_algo_param_dict = {}


def array2pix(image, ismask=False):
    if len(image.shape) == 2:
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGRA)

    if image.shape[2] == 1:
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGRA)

    if image.shape[2] == 3:
        # image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
    # show1 = cv2.resize(image, (640, 480))
    if ismask:
        # image[:,:,3] = image[:,:,2]
        pass

    show1 = image
    # QtImg = QImage(show1.data, show1.shape[1], show1.shape[0], QImage.Format_BGR888)
    QtImg = QImage(
        show1.data, show1.shape[1], show1.shape[0], QImage.Format_ARGB32)
    pixmap = QPixmap(QtImg)
    return pixmap


class ImageWithResizableBox(QWidget):
    def __init__(self, test_config):
        '''

        :param imagePath:
        :param default_threshold_list: 电线高度 px; 相机中心点 px px，距离 px，角度 degree；
        '''
        super().__init__()

        self.origin_scale = test_config.get('scale', 0.5)
        self.img_glob_str = test_config.get('img_glob')

        self.ls_glob = glob.glob(self.img_glob_str)
        self.img_index = 0

        self.setFocusPolicy(Qt.StrongFocus)
        self.setFocus()
        self.is_ctrl_pressed = False  # ctrl 按下

        self.buffer = {}  # group_id : {'rect':[QRectF, box_name], 'is_drag':False, kp_name:QPointF}
        self.load_img_annotator()

    def load_img_annotator(self):

        # 清理旧资源
        for group_id, item in self.buffer.items():
            if 'rect' in item:
                combo_box = item['rect'][1]

                if combo_box:
                    combo_box.deleteLater()  # 安全删除 ComboBox

        self.buffer.clear()  # 清空 buffer

        # 接下来是加载新图像和标注的逻辑 ...

        self.imagePath = self.ls_glob[self.img_index]

        le = len(self.ls_glob[self.img_index].split('.')[-1])
        self.json_path = self.ls_glob[self.img_index][:-le] + 'json'

        # 设置图片
        if isinstance(self.imagePath, numpy.ndarray):
            self.orig_pixmap = array2pix(self.imagePath)
        else:
            self.orig_pixmap = QPixmap(self.imagePath)  # 用于缩放
        self.chk_scaleimg_x1, self.chk_scaleimg_y1 = 0, 0  # 图片左上角 相对窗口坐标系

        self.scale = self.origin_scale
        self.orig_scale = self.scale
        self.orig_img_height, self.orig_img_width = self.orig_pixmap.height(), self.orig_pixmap.width()
        self.pixmap = self.orig_pixmap.scaled(int(self.orig_pixmap.width() * self.scale),
                                              int(self.orig_pixmap.height() * self.scale), Qt.KeepAspectRatio,
                                              Qt.SmoothTransformation)
        window_title = f'{self.img_index + 1}/{len(self.ls_glob)}  {self.ls_glob[self.img_index]} '
        self.setWindowTitle(window_title)
        self.resize(self.pixmap.width(), self.pixmap.height())  # 调整窗口大小以适应图片

        # 载入标注文件
        with open(self.json_path, 'r') as load_f:
            self.labelmepose_content = json.load(load_f)
        # self.cls_names = ['person_Place', 'person_NoPlace', 'person_Other']
        self.cls_names = ['ZhCMFangBao', 'ZhCMFuKuang',
                          'ZhCMNaKuang', 'ZhCMZhanLi', 'BMFangBao', 'BMZhanLi',
                          'AnJianYuan', 'Other']  # NaBao
        # self.cls_names = ['ZhCMFangBao', 'ZhCMFuKuang',
        #                   'ZhCMNaKuang',  'ZhCMNaBao', 'ZhCMZhanLi',  'BMNaKuang', 'BMNaBao','BMFangBao',  'BMZhanLi',
        #                   'AnJianYuan','Other'] # NaBao
        self.china_cls_names = ['正侧面放包', '正侧面扶框',
                                '正侧面拿框', '正侧面站立', '背面放包', '背面站立',
                                '安检员', '其他']
        self.old_new_clsname_dict = {'person_Place': 'ZhCMFangBao', 'person_NoPlace': 'ZhCMZhanLi',
                                     'person_Other': 'Other'}

        # self.cls_names_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]  # rgb
        self.cls_names_colors = [(255, 0, 0), (255, 0, 0),
                                 (0, 255, 0), (0, 255, 0), (0, 255, 0), (0, 255, 0),
                                 (0, 0, 255), (0, 0, 255), ]  # rgb

        self.kp_names = ['left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow', 'left_wrist', 'right_wrist']
        self.kp_names_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 0, 0), (255, 255, 255), (255, 255, 0)]

        self.lines = [('left_shoulder', 'left_elbow'), ('left_elbow', 'left_wrist'), ('right_shoulder', 'right_elbow'),
                      ('right_elbow', 'right_wrist')]  # 显示用
        self.lines_colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 0, 0), ]

        # labelmepose_content 2 buffer
        self.handle_size = 20

        for shape_dict in self.labelmepose_content['shapes']:
            if shape_dict['shape_type'] == 'rectangle':
                [x1, y1], [x2, y2] = shape_dict['points']
                box_name = shape_dict['label']
                if self.old_new_clsname_dict.get(box_name):
                    box_name = self.old_new_clsname_dict[box_name]
                group_id = shape_dict['group_id']
                w, h = x2 - x1, y2 - y1
                qrect = QRectF(x1 * self.scale, y1 * self.scale, w * self.scale, h * self.scale)
                # 创建 QComboBox
                combo_box = QComboBox(self)
                combo_box.setStyleSheet("""
                    QComboBox {
                        background-color: rgba(255, 255, 255, 255); /* 完全透明背景 */
                        color: black; /* 文字颜色 */
                        border: none; /* 无边框 */
                        padding: 0px 0px 0px 0px; /* 内边距 */
                        width: 150px; /* 固定宽度 */
                    }
                    QComboBox QAbstractItemView {
                        background-color: rgba(255, 255, 255, 200); /* 半透明下拉列表背景 */
                        selection-background-color: rgba(0, 0, 255, 150); /* 半透明选中项背景颜色 */
                    }
                """)
                # combo_box.addItems(self.cls_names+self.kp_names)
                # combo_box.addItems(self.cls_names + self.kp_names)
                for china_name, en_name in zip((self.china_cls_names + self.kp_names),
                                               (self.cls_names + self.kp_names)):
                    combo_box.addItem(china_name, en_name)

                # combo_box.setCurrentText(box_name)
                combo_box.setCurrentIndex(self.cls_names.index(box_name))
                combo_box.move(x1 * self.scale, y1 * self.scale)
                # combo_box.move((x1+x2)//2 * self.scale, (y1+y2)//2 * self.scale)
                # combo_box.currentIndexChanged.connect(self.combo_box_slot) #
                combo_box.currentIndexChanged.connect(partial(self.combo_box_slot, group_id=group_id))  #

                self.buffer[group_id] = {
                    'rect': [qrect, combo_box, box_name],
                    'is_drag': False,
                }
                # self.rect_list.append(qrect)
            if shape_dict['shape_type'] == 'point':
                [x, y] = shape_dict['points'][0]
                group_id = shape_dict['group_id']
                kp_name = shape_dict['label']
                self.buffer[group_id][kp_name] = QPointF(x * self.scale, y * self.scale)  # 创建点
                index = combo_box.findText(kp_name, Qt.MatchExactly)  # todo
                if x == 0 and y == 0:
                    self.buffer[group_id]['rect'][1].setItemData(index, QColor(255, 0, 0), role=Qt.ForegroundRole)  # 红
                else:
                    self.buffer[group_id]['rect'][1].setItemData(index, QColor(0, 0, 0), role=Qt.ForegroundRole)  #
        self.update()

    def paintEvent(self, event):
        try:
            print('paintEvent')

            window_title = f'{self.img_index + 1}/{len(self.ls_glob)}  {self.ls_glob[self.img_index]} '
            # self.resize(self.pixmap.width(), self.pixmap.height())  # 调整窗口大小以适应图片
            painter = QPainter(self)
            painter.drawPixmap(self.chk_scaleimg_x1, self.chk_scaleimg_y1, self.pixmap)  # 画图 x1y1
            # painter.drawPixmap(-100, -300, self.pixmap)  # 画图 x1y1

            painter.setRenderHint(QPainter.Antialiasing)
            # pen = QPen(QColor(255, 0, 0), 2)
            # painter.setPen(pen)

            # 绘制矩形，矩形边角方框， 点， 线
            for group_id, item_dict in self.buffer.items():

                rect = item_dict['rect'][0]
                combo_box = item_dict['rect'][1]
                r, g, b = self.cls_names_colors[combo_box.currentIndex()]
                line_width = 8 if item_dict['is_drag'] else 2

                painter.setPen(QPen(QColor(r, g, b), line_width))
                painter.drawRect(rect)  # 画矩形
                combo_box.move(rect.x(), rect.y())  # 移动label位置
                combo_box.show()
                # combo_box.move(rect.center().x(),rect.center().y())
                for corner in [(rect.topLeft(), 1), (rect.topRight(), 2),
                               (rect.bottomRight(), 3), (rect.bottomLeft(), 4)]:
                    painter.drawRect(corner[0].x() - self.handle_size // 2,
                                     corner[0].y() - self.handle_size // 2,
                                     self.handle_size, self.handle_size)

                # 画点 线
                for ind, kp_name in enumerate(self.kp_names):
                    if kp_name in item_dict:
                        r, g, b = self.kp_names_colors[ind]
                        painter.setPen(QPen(QColor(r, g, b), 10))
                        painter.drawPoint(item_dict[kp_name])
                        # 显示0点 下拉框项为红色
                        x, y = item_dict[kp_name].x(), item_dict[kp_name].y()
                        combox_index = combo_box.findText(kp_name, Qt.MatchExactly)  # todo
                        if x == 0 and y == 0:
                            item_dict['rect'][1].setItemData(combox_index, QColor(255, 0, 0), role=Qt.ForegroundRole)
                        else:
                            item_dict['rect'][1].setItemData(combox_index, QColor(0, 0, 0), role=Qt.ForegroundRole)

                for ind, line in enumerate(self.lines):
                    r, g, b = self.lines_colors[ind]
                    painter.setPen(QPen(QColor(r, g, b), line_width))
                    p1, p2 = item_dict[line[0]], item_dict[line[1]]
                    if (p1.x() == 0 and p1.y() == 0) or (p2.x() == 0 and p2.y() == 0):
                        continue
                    painter.drawLine(item_dict[line[0]], item_dict[line[1]])

                if item_dict['is_drag']:
                    window_title += '\t(' + item_dict['drag_infor'] + ") " + f"\t(group_id {group_id}) "

            self.setWindowTitle(window_title)
            # # 设置字体
            # font = QFont('Arial', 18)
            # painter.setFont(font)
            #
            # painter.setPen(QPen(QColor(0, 0, 255), 2))
            # painter.drawText(40, 560, f'相机盖原点 x y:{self.threshold_list[1]} {self.threshold_list[2]}')
            # painter.drawText(40, 600, f'相机盖角度:{self.threshold_list[3]} 度')
            # painter.drawText(40, 640, f'相机盖距离:{self.threshold_list[4]}')
            # painter.setPen(QPen(QColor(255, 0, 0), 2))
            # painter.drawText(40, 680, f'电线高度阈值:{self.threshold_list[0]} ')  # 文字左下角的位置 (x, y)
        except:
            print(traceback.format_exc())

    def mouseDoubleClickEvent(self, event):
        self.update()

    def mousePressEvent(self, event):  # 鼠标按下
        try:
            print('mousePressEvent')
            if event.button() == Qt.LeftButton:

                if self.is_ctrl_pressed:
                    # 平移图片
                    self.last_mouse_globalpos = event.globalPos()
                    return

                # 选择选中的矩形角点
                # for rect_ind, rect in enumerate(self.rect_list):
                is_qf_drag = False
                for group_id, item_dict in self.buffer.items():
                    #  矩形
                    qrect = item_dict['rect'][0]
                    for corner, name in [(qrect.topLeft(), 'rect topLeft'), (qrect.topRight(), 'rect topRight'),
                                         (qrect.bottomRight(), 'rect bottomRight'),
                                         (qrect.bottomLeft(), 'rect bottomLeft')]:
                        print(event.globalPos())  # 全局坐标
                        print(event.pos())  # 局部坐标
                        print((event.globalPos() - self.mapToGlobal(corner.toPoint())).manhattanLength())
                        if (event.globalPos() - self.mapToGlobal(
                                corner.toPoint())).manhattanLength() <= self.handle_size * 2:
                            item_dict['is_drag'] = True  # 是否选中
                            is_qf_drag = True
                            item_dict['drag_infor'] = name
                            self.current_qf = qrect
                            # 改变鼠标形状为“选中”或手势指示的光标
                            hand_cursor = QCursor(Qt.PointingHandCursor)
                            self.setCursor(hand_cursor)
                            break
                    if item_dict['is_drag']:
                        break
                    # kp
                    for kp_name in self.kp_names:
                        if kp_name in item_dict:
                            if (event.globalPos() - self.mapToGlobal(
                                    item_dict[kp_name].toPoint())).manhattanLength() <= self.handle_size / 2:
                                item_dict['is_drag'] = True  # 是否选中
                                is_qf_drag = True
                                item_dict['drag_infor'] = kp_name
                                self.current_qf = item_dict[kp_name]
                                # 改变鼠标形状为“选中”或手势指示的光标
                                hand_cursor = QCursor(Qt.PointingHandCursor)
                                self.setCursor(hand_cursor)
                                break
                # if not is_qf_drag: # 没有选中 拖动图片

        except:
            print(traceback.format_exc())

    def mouseMoveEvent(self, event):  # 鼠标移动
        try:
            print('mouseMoveEvent')

            if self.is_ctrl_pressed:
                # # 平移图片
                global_pos = event.globalPos()
                dx = global_pos.x() - self.last_mouse_globalpos.x()
                dy = global_pos.y() - self.last_mouse_globalpos.y()

                self.chk_scaleimg_x1 += dx
                self.chk_scaleimg_y1 += dy  # update()里更新显示图片

                # 平移buffer
                for group_id, item_dict in self.buffer.items():
                    qrect = item_dict['rect'][0]
                    combox = item_dict['rect'][1]
                    qrect.moveTo(qrect.x() + dx,
                                 qrect.y() + dy)  # 移动矩形
                    combox.move(combox.x() + dx,
                                combox.y() + dy)  # 移动combox

                    for kp_name in self.kp_names:
                        if kp_name in item_dict:
                            qkp = item_dict[kp_name]
                            if qkp.x() == 0 and qkp.y() == 0:
                                continue
                            item_dict[kp_name] = QPointF(qkp.x() + dx, qkp.y() + dy)  # 移动点

                self.last_mouse_globalpos = global_pos
                self.update()
                return

            # 交互式修改阈值
            global_pos = event.globalPos()
            # for rect_ind, dragging_listconer in enumerate(self.dragging_listrect_listconer): # 每个矩形框
            for group_id, item_dict in self.buffer.items():
                is_dragging = item_dict['is_drag']
                if is_dragging:
                    drag_infor = item_dict['drag_infor']
                    is_rect = drag_infor.split(' ')[0] == 'rect'
                    if is_rect:
                        coner_name = drag_infor.split(' ')[1]
                        qrect = item_dict['rect'][0]
                        if coner_name == 'topLeft':
                            qrect.setTopLeft(self.mapFromGlobal(global_pos))  # 这里移动矩形角点
                        elif coner_name == 'topRight':
                            qrect.setTopRight(self.mapFromGlobal(global_pos))
                        elif coner_name == 'bottomRight':
                            qrect.setBottomRight(self.mapFromGlobal(global_pos))
                        elif coner_name == 'bottomLeft':
                            qrect.setBottomLeft(self.mapFromGlobal(global_pos))
                    else:  # kp
                        kp_name = drag_infor
                        item_dict[kp_name] = QPointF(self.mapFromGlobal(global_pos))

            self.update()  # 执行paintEvent()
        except:
            print(traceback.format_exc())

    def mouseReleaseEvent(self, event):  # 鼠标释放
        try:
            print('mouseReleaseEvent')
            # param_dict = read_yaml(self.param_path)
            # if param_dict:
            #     param_dict['step1'] = self.threshold_list
            #     # param_dict['step1'] = [1,23]
            #     # write_yaml(param_dict, self.param_path)
            #
            #     # write_yaml(param_dict['step1'], self.param_path+'_step1.yaml')
            #     saved_algo_param_dict['step1'] = self.threshold_list
            for group_id, item_dict in self.buffer.items():
                is_dragging = item_dict['is_drag']
                if is_dragging:
                    item_dict['is_drag'] = False
            self.setCursor(QCursor(Qt.ArrowCursor))  # 默认箭头
            # self.update_annonation()
            self.update()
        except:
            print(traceback.format_exc())

    def wheelEvent(self, event):  # 鼠标滚动
        try:
            print('wheelEvent')
            if not self.is_ctrl_pressed:
                return

            print(event.angleDelta().x())
            print(event.angleDelta().y())  # 120 -120
            print(event.globalPos())  # 全局坐标 屏幕？
            print(event.pos())  # 局部坐标 窗口？

            # 1 以鼠标为原点 缩放图像
            pre_scale = self.scale
            step_len = 0.05 * self.scale * event.angleDelta().y() / 120 * 5
            print(f'step_len {step_len}')
            # self.scale = self.scale*self.scale/self.orig_scale*event.angleDelta().y() / 120
            self.scale = self.scale + step_len  # 1%
            chk_shb_x, chk_shb_y = event.pos().x(), event.pos().y()  # 相对窗口坐标系 鼠标坐标

            tx_shb_x, tx_shb_y = (chk_shb_x - self.chk_scaleimg_x1), (
                    chk_shb_y - self.chk_scaleimg_y1)  # 计算图像左上角 相对窗口坐标系
            self.chk_scaleimg_x1 = self.chk_scaleimg_x1 - step_len * tx_shb_x / pre_scale
            self.chk_scaleimg_y1 = self.chk_scaleimg_y1 - step_len * tx_shb_y / pre_scale  # 平移

            # 缩放图片
            self.pixmap = self.orig_pixmap.scaled(int(self.orig_img_width * self.scale),
                                                  int(self.orig_img_height * self.scale),
                                                  Qt.KeepAspectRatio, Qt.SmoothTransformation)
            # painter = QPainter(self)
            # painter.drawPixmap(0, 0, self.pixmap)  # 画图

            # # 2 缩放平移矩形框
            # 矩形左上角 相对窗口坐标系
            # for qrect in self.rect_list:
            for group_id, item_dict in self.buffer.items():
                qrect = item_dict['rect'][0]
                chk_rect_x1, chk_rect_y1 = qrect.topLeft().x(), qrect.topLeft().y()
                chk_rect_x1 = (chk_rect_x1 - chk_shb_x) / pre_scale * self.scale + chk_shb_x
                chk_rect_y1 = (chk_rect_y1 - chk_shb_y) / pre_scale * self.scale + chk_shb_y  # 平移

                # chk_rect_x1 = chk_rect_x1 - step_len * tx_shb_x / pre_scale
                # chk_rect_y1 = chk_rect_y1 - step_len * tx_shb_y / pre_scale
                w, h = qrect.width() / pre_scale * self.scale, qrect.height() / pre_scale * self.scale
                qrect.setRect(chk_rect_x1, chk_rect_y1, w, h)

                # 缩放点
                for kp_name in self.kp_names:
                    qkp = item_dict[kp_name]
                    kp_x, kp_y = qkp.x(), qkp.y()
                    if kp_x == 0 and kp_y == 0:
                        continue
                    kp_x = (kp_x - chk_shb_x) / pre_scale * self.scale + chk_shb_x
                    kp_y = (kp_y - chk_shb_y) / pre_scale * self.scale + chk_shb_y  # 平移
                    item_dict[kp_name] = QPointF(kp_x, kp_y)
                    # qkp.rx = kp_x
                    # qkp.ry = kp_y

            self.update()  # paintEvent

        except:
            print(traceback.format_exc())

    def closeEvent(self, event):
        # saved_algo_param_dict['step1'] = []
        self.update_annonation()

    def update_annonation(self):  # self.buffer 2 elf.labelmepose_content
        # for group_id, item_dict in self.buffer.items():
        #     qrect = item_dict['rect'][0]
        #     combox = item_dict['rect'][1]

        for shape_dict in self.labelmepose_content['shapes']:
            group_id = shape_dict['group_id']
            buffer_item_dict = self.buffer[group_id]
            if shape_dict['shape_type'] == 'rectangle':
                qrect = buffer_item_dict['rect'][0]
                combox = buffer_item_dict['rect'][1]

                top_left = qrect.topLeft()  # 左上角 QPointF
                bottom_right = qrect.bottomRight()  # 右下角 QPointF
                x1, y1 = top_left.x(), top_left.y()  # 相对于窗口
                x2, y2 = bottom_right.x(), bottom_right.y()
                # current_label = combox.currentText()
                current_label = combox.currentData()
                shape_dict['points'] = [
                    [(x1 - self.chk_scaleimg_x1) / self.scale, (y1 - self.chk_scaleimg_y1) / self.scale],
                    [(x2 - self.chk_scaleimg_x1) / self.scale, (y2 - self.chk_scaleimg_y1) / self.scale]]  # 保存矩形
                shape_dict['label'] = current_label  # 同步标签

            if shape_dict['shape_type'] == 'point':
                kp_name = shape_dict['label']
                qp = buffer_item_dict[kp_name]
                x, y = qp.x(), qp.y()  # 相对于窗口
                if x == 0 and y == 0:
                    continue
                shape_dict['points'] = [
                    [(x - self.chk_scaleimg_x1) / self.scale, (y - self.chk_scaleimg_y1) / self.scale]]  # 同步kp

            # json_path = r"D:\DATA\20250519RENBAO\temp\annotated\0.json"
        with open(self.json_path, 'w', encoding='utf-8') as f:
            json.dump(self.labelmepose_content, f, ensure_ascii=False, indent=4)
        print(f"标注信息已保存至 {self.json_path}")

    def combo_box_slot(self, index, group_id):  # 调整0点，类名 逻辑
        try:
            combox = self.buffer[group_id]['rect'][1]
            qrect = self.buffer[group_id]['rect'][0]
            last_box_name = self.buffer[group_id]['rect'][2]
            # current_label = combox.currentText()
            current_label = combox.currentData()
            if current_label in self.cls_names:  # 更新类名 UI 2 BUFFER
                self.buffer[group_id]['rect'][2] = current_label  # 维护 用于回显
                self.update()  # 执行paintEvent
            elif current_label in self.kp_names:  # 额外功能 添加kp
                # self.is_add_kp = True
                # self.add_kp_name = current_label

                # # 添加kp
                # x, y = qrect.center().x(), qrect.center().y()
                # self.buffer[group_id][current_label] = QPointF(x - 40, y - 40)

                # v2 更改所有0点
                offset_inds = [0,3,1,4,2,5] # 左上右下
                for ind, kp_name in enumerate(self.kp_names):
                    kp = self.buffer[group_id][kp_name]
                    if kp.x()==0 and kp.y()==0:
                        x1, y1 = qrect.topLeft().x(), qrect.topLeft().y()
                        w,h = qrect.width(), qrect.height()
                        offset_x = w * (offset_inds[ind]+1)/(len(self.kp_names)+1)
                        offset_y = h * (offset_inds[ind]+1)/(len(self.kp_names)+1)
                        self.buffer[group_id][kp_name] = QPointF(x1+offset_x, y1+offset_y)

                # combox.setCurrentText(box_name)  #
                combox.setCurrentIndex(self.cls_names.index(last_box_name))
        except:
            print(index)
            print(group_id)
            print(traceback.format_exc())

    def keyPressEvent(self, event):  # 键盘按下事件
        print('keyPressEvent')
        try:

            if event.key() == Qt.Key_Space:  # 跳转下一张图片
                self.update_annonation()
                self.img_index = (self.img_index + 1) % len(self.ls_glob)

                self.load_img_annotator()
                print()
                # self.close()
                # self.deleteLater()
                # nw = ImageWithResizableBox(self.ls_glob[self.img_index])
                # nw.show()

            elif event.key() == Qt.Key_B:  #
                self.update_annonation()
                # elif event.text().lower() == 'b':
                self.img_index = (self.img_index - 1) % len(self.ls_glob)

                self.load_img_annotator()

            elif event.key() == Qt.Key_Control:
                self.is_ctrl_pressed = True
        except:
            print(traceback.format_exc())

    def keyReleaseEvent(self, event):  # 键盘释放事件
        print('keyReleaseEvent')
        if event.key() == Qt.Key_Control:
            self.is_ctrl_pressed = False
            pass


if __name__ == "__main__":

    app = QApplication(sys.argv)
    # img_glob = r"D:\DATA\20250519RENBAO\temp\annotated\*.jpg"
    # img_glob = r"D:\DATA\20250519RENBAO\trainV8Pose_people\add_imgs\test10\*.jpg"
    # img_glob = r'D:\DATA\20250519RENBAO\caitu\20250527_annotated_100_200\*.jpg'

    test_config = {
        'img_glob': r'D:\DATA\20250519RENBAO\temp\20250609102346_mid_cam_t23725-2025-05-13_16-48-43.mp4_frames\annotated\*.jpg',
        'scale': 1.25,
    }

    try:
        # widget = ImageWithResizableBox(img_path)  # 替换为初始图片路径
        widget = ImageWithResizableBox(test_config)  # 替换为初始图片路径
        print("初始图片路径:", test_config['img_glob'])
    except:
        print(traceback.format_exc())
    widget.resize(widget.pixmap.width(), widget.pixmap.height())  # 调整窗口大小以适应图片
    widget.show()
    sys.exit(app.exec_())
